package nina.yiyou.attendance.s10merge.compute.latepoint

import nina.yiyou.attendance.s10merge.compute.AttendDetailMerger
import spock.lang.Specification

import java.time.LocalDate
import java.time.LocalTime

class LatePointCalculatorTest extends Specification {

  List<List> _dayList
  List _curDay

  List _defaultPoint

  void setup() {
    _defaultPoint = [
        [9, 30],
        [12, 30],
        [14, 00],
    ]
  }

  def "Calc:普通下班"() {
    given:
    _dayList = [
        [[2020, 1, 2], [9, 29], [+0, [18, 31]]],
        [[2020, 1, 3], [9, 28], [+0, [18, 32]]],
    ]
    _curDay = _dayList[1]

    when:
    def result = calc()

    then:
    result == [[2020, 1, 3], [9, 30]]
  }

  def "Calc:普通下班2"() {
    given:
    _dayList = [
        [[2020, 4, 21], [9, 29], [+0, [21, 00]]],
        [[2020, 4, 22], [9, 28], [+0, [18, 32]]],
    ]
    _curDay = _dayList[1]
    _defaultPoint[0] = [10, 00]

    when:
    def result = calc()

    then:
    result == [[2020, 4, 22], [10, 00]]
  }

  def "Calc:外部指定迟到线"() {
    given:
    _dayList = [
        [[2020, 1, 2], [9, 29], [+0, [18, 31]]],
        [[2020, 1, 3], [9, 28], [+0, [18, 32]], ['迟到线': [12, 34]]],
    ]
    _curDay = _dayList[1]

    when:
    def result = calc()

    then:
    result == [[2020, 1, 3], [12, 34]]
  }

  def "Calc:前一天早下班"() {
    given:
    _dayList = [
        [[2022, 11, 12], [9, 29], [+0, [20, 59]]],
        [[2022, 11, 13], [9, 28], [+0, [18, 32]]],
    ]
    _curDay = _dayList[1]
    _defaultPoint[0] = [10, 00]

    when:
    def result = calc()

    then:
    result == [[2022, 11, 13], [9, 30]]
  }

  def "Calc:前一天不用上班"() {
    given:
    _dayList = [
        [[2020, 2, 3], [9, 29], [+0, [19, 11]]],
        [[2020, 2, 6], [9, 18], [+0, [18, 32]]],
    ]
    _curDay = _dayList[1]

    when:
    def result = calc()

    then:
    result == [[2020, 2, 6], [9, 30]]
  }

  def "Calc:加班过10点"() {
    given:
    _dayList = [
        [[2020, 2, 12], [9, 28], [+0, [22, 57]]],
        [[2020, 2, 13], [9, 29], [+0, [18, 31]]],
    ]
    _curDay = _dayList[1]

    when:
    def result = calc()

    then:
    result == [[2020, 2, 13], [10, 00]]
  }

  def "Calc:加班过12点迟小到"() {
    given:
    _dayList = [
        [[2020, 3, 17], [9, 29], [+1, [1, 12]]],
        [[2020, 3, 18], [10, 28], [+0, [22, 57]]],
    ]
    _curDay = _dayList[1]

    when:
    def result = calc()

    then:
    result == [[2020, 3, 18], [10, 00]]
  }

  def "Calc:加班过3点迟大到"() {
    given:
    _dayList = [
        [[2021, 3, 17], [9, 29], [+1, [4, 42]]],
        [[2021, 3, 18], [12, 28], [+0, [22, 57]]],
    ]
    _curDay = _dayList[1]

    when:
    def result = calc()

    then:
    result == [[2021, 3, 18], [14, 00]]
  }

  /**
   * @see LatePointCalculator#calc
   */
  List calc() {
    def time = { List<Integer> t -> t ? LocalTime.of(t[0], t[1]) : null }

    def mockDay = { List<List> d ->
      def d0 = d[0] as List<Integer>
      def date = LocalDate.of(d0[0], d0[1], d0[2])
      def stub = Stub(AttendDetailMerger.PunchDay)
      stub.date() >> { date }

      def d1 = d[1] as List<Integer>
      stub.punchIn() >> { date.atTime(d1[0], d1[1]) }

      def d2 = d[2] as List
      def d21 = d2[1] as List<Integer>
      stub.punchOut() >> { date.plusDays((int) d2[0]).atTime(d21[0], d21[1]) }

      def d3 = (d.size() > 3 ? d[3] : []) as Map
      stub.overrideLatePoint() >> { time(d3['迟到线'] as List) }

      return stub
    }

    def curDay = mockDay(_curDay)
    def pointTime = { List<Integer> l -> curDay.date().atTime(l[0], l[1]) }

    def defaultPoint = Stub(LatePointCalculator.DefaultPoint)
    defaultPoint.amIn() >> { pointTime(_defaultPoint[0] as List) }
    defaultPoint.amOut() >> { pointTime(_defaultPoint[1] as List) }
    defaultPoint.pmIn() >> { pointTime(_defaultPoint[2] as List) }

    def result = new LatePointCalculator(curDay, _dayList.collect { mockDay(it) }, defaultPoint).calc()
    return [[result.year, result.monthValue, result.dayOfMonth], [result.hour, result.minute]]
  }
}
